package com.tanxi521.commandmanager;

import com.tanxi521.commandmanager.Listener.CraftTableListener;
import com.tanxi521.commandmanager.Listener.DropListener;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryCreativeEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.*;
import org.bukkit.event.vehicle.VehicleEnterEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

public final class CommandManager extends JavaPlugin {

    public static CommandManager instance;

    public static CommandManager getInstance() {
        return instance;
    }

    @Override
    public void onLoad() {
        super.onLoad();
        instance = this;
    }

    @Override
    public void onEnable() {
        // Plugin startup logic
        saveDefaultConfig();
        getLogger().info("§e版本号: " + getDescription().getVersion());
        getLogger().info("§e作者: " + getDescription().getAuthors());
        getLogger().info("§e联系方式: QQ 1254806967");
        Bukkit.getPluginManager().registerEvents(new CommanderListener(), this);
        Bukkit.getPluginManager().registerEvents(new CraftTableListener(), this);
        Bukkit.getPluginManager().registerEvents(new DropListener(), this);
        // 注册指令
        Optional.ofNullable(Bukkit.getPluginCommand("bugM"))
                .ifPresent(pluginCommand -> {
                    pluginCommand.setExecutor(new BugMCommand());
                });

        File file = new File(CommandManager.getInstance().getDataFolder(), "blockLog");
        if (!file.exists()) file.mkdir();

    }

    @Override
    public void onDisable() {
        // Plugin shutdown logic
    }

    public static class ConfigReader {

        public static FileConfiguration config = getInstance().getConfig();

        public static List<String> getWhiteList() {
            return config.getStringList("whiteList");
        }

        public static List<String> getCommandList() {
            return config.getStringList("CommandList");
        }

        public static List<String> getCreative() {
            return config.getStringList("CreativePermission");
        }

        public static List<String> getPack() {
            return config.getStringList("packItem");
        }

        public static List<String> getNotShiftGui() {
            return config.getStringList("guiNotShift");
        }

        public static String getRestartTime() {
            return config.getString("restartTime");
        }

    }

    public static class CommanderListener implements Listener {

        @EventHandler
        public void onPlayerCommand(PlayerCommandPreprocessEvent e) {
            Player player = e.getPlayer();
            this.playerIsOp(player);
            if (ConfigReader.getWhiteList().contains(player.getName())) return;
            String command = e.getMessage();

            Inventory topInventory = player.getOpenInventory().getTopInventory();
            String defaultTitle = topInventory.getType().name();
            if (defaultTitle.equalsIgnoreCase(CHEST) || defaultTitle.equalsIgnoreCase(ITEM_HOPPER)) {
                if (!(command.startsWith("minepay") || command.startsWith("mp"))) e.setCancelled(true);
            }

            ConfigReader.getCommandList().forEach(limit -> {
                if (command.contains(limit)) {
                    e.setCancelled(true);
                    player.kickPlayer("§c你没有执行此命令的权限");
                }
            });


            if (command.startsWith("/register")) {
                Plugin authMe = Bukkit.getPluginManager().getPlugin("AuthMe");
                if (null == authMe) return;
                String[] s = command.split(" ");
                if (s.length != 3) return;
                if (!s[1].equals(s[2])) return;
                e.setCancelled(true);
                Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "authme register " + player.getName()
                        + " " + s[2]);
            }

        }

        @EventHandler
        public void onSwapHandItems(PlayerSwapHandItemsEvent e) {
            Player player = e.getPlayer();
            ItemStack mainHandItem = e.getMainHandItem();
            String name = mainHandItem.getType().name();
            ItemStack offHandItem = e.getOffHandItem();
            String off = offHandItem.getType().name();

            List<String> pack = ConfigReader.getPack();
            for (String p : pack) {
                if (off.contains(p) || name.contains(p)) {
                    player.sendMessage("背包类物品禁止放副手");
                    e.setCancelled(true);
                    return;
                }
            }
        }


        @EventHandler
        public void onInventoryClick(InventoryCreativeEvent e) {
            HumanEntity whoClicked = e.getWhoClicked();
            String name = whoClicked.getName();
            if (ConfigReader.getCreative().contains(name)) return;
            e.setCancelled(true);
            Player player = (Player) whoClicked;
            Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "clear " + name);
            player.kickPlayer("");
        }

        @EventHandler
        public void onExtraBug2Click(InventoryClickEvent e) {
            if (null == extraBugMap.get(e.getWhoClicked().getName())) return;
            List<String> notShiftGui = ConfigReader.getNotShiftGui();
            boolean isBanedGui = false;
            for (String guiName : notShiftGui) {
                if (isBanedGui) break;
                if (extraBugMap.get(e.getWhoClicked().getName()).startsWith(guiName)) isBanedGui = true;
            }
            if (!isBanedGui) return;
            if (!e.isShiftClick()) return;
            e.getWhoClicked().sendMessage("该设备禁止shift点击");
            e.setCancelled(true);
        }

        @EventHandler
        public void onPlayerJoin(PlayerLoginEvent e) {
            Player player = e.getPlayer();
            PlayerInventory inventory = e.getPlayer().getInventory();
            ItemStack itemInOffHand = inventory.getItemInOffHand();
            String off = itemInOffHand.getType().name();
            List<String> pack = ConfigReader.getPack();

            for (String name : pack) {
                if (off.contains(name)) {
                    player.kickPlayer("§c背包数据异常,请联系管理员");
                    return;
                }
            }
        }

        @EventHandler
        public void onPlayerCloseInventory(InventoryCloseEvent e) {
            PlayerInventory inventory = e.getPlayer().getInventory();
            ItemStack itemInOffHand = inventory.getItemInOffHand();
            String itemName = itemInOffHand.getType().name();
            List<String> pack = ConfigReader.getPack();
            for (String name : pack) {
                if (itemName.contains(name)) {
                    inventory.setItemInOffHand(new ItemStack(Material.AIR));
                    e.getPlayer().sendMessage("§c检测到异常行为,已删除副手");
                    return;
                }
            }
        }

        @EventHandler
        public void onPlayerShiftRight(PlayerInteractEvent e) {
            final Player player = e.getPlayer();
            final PlayerInventory inventory = player.getInventory();
            final ItemStack item = player.getInventory().getItemInMainHand();
            final String itemName = item.getType().name();
            final List<String> pack = ConfigReader.getPack();
            int count = 0;

            for (ItemStack itemStack : inventory) {
                if (itemStack == null) continue;
                Material type = itemStack.getType();
                String name = type.name();
                if (pack.contains(name)) count += itemStack.getAmount();
            }

            for (String name : pack) {
                if (itemName.contains(name) && count > 1) {
                    e.setCancelled(true);
                    player.sendMessage("§c身上最多只能同时存在1个热力背包");
                    return;
                }
            }

            // 检测是否是右键点击
            if (e.getAction().name().contains("RIGHT")) {
                // 检测是否同时按下了Shift键
                if (player.isSneaking()) {
                    for (String name : pack) {
                        if (itemName.contains(name)) {
                            e.setCancelled(true);
                            player.sendMessage("§c背包编辑模式禁用");
                            return;
                        }
                    }
                }
            }
        }

        public static final String CHEST = "chest";
        public static final String ITEM_HOPPER = "item hopper";

        @EventHandler
        public void playerGetItem(EntityPickupItemEvent e) {
            LivingEntity entity = e.getEntity();

            if (!(entity instanceof Player)) return;
            Player player = (Player) entity;
            Inventory topInventory = player.getOpenInventory().getTopInventory();
            String defaultTitle = topInventory.getType().name();
            if (defaultTitle.equalsIgnoreCase(CHEST) || defaultTitle.equalsIgnoreCase(ITEM_HOPPER)) {
                e.setCancelled(true);
                player.sendMessage("§c查看gui时无法拾取物品");
            }

        }

        public static final ConcurrentHashMap<String, ClickCounter> clickMap = new ConcurrentHashMap<>();

        @EventHandler
        public void onItemSpawn(ItemSpawnEvent e) {
            Item entity = e.getEntity();
            ItemStack itemStack = entity.getItemStack();
            int amount = itemStack.getAmount();
            String name = itemStack.getType().name();
            List<String> pack = ConfigReader.getPack();
            for (String packName : pack) {
                if (name.contains(packName) && amount > 1) {
                    itemStack.setAmount(1);
                    return;
                }

            }
        }

        @EventHandler
        public void onBAGChange(InventoryClickEvent e) {
            HumanEntity whoClicked = e.getWhoClicked();

            List<String> pack = ConfigReader.getPack();

            ItemStack cursor = e.getCursor();
            String hoverName = cursor.getType().name();

            int slot = e.getSlot();
            if (e.getClick().isKeyboardClick()) {
                if (slot == 40) {
                    e.setCancelled(true);
                    return;
                }

                String itemName = e.getCurrentItem().getType().name();

                for (String name : pack) {
                    if (itemName.contains(name) || hoverName.contains(name)) {
                        e.setCancelled(true);
                        return;
                    }
                }
            }
            ItemStack currentItem = e.getCurrentItem();
            for (String name : pack) {
                if (hoverName.contains(name) && slot == 40) {
                    e.setCancelled(true);
                    return;
                }
                if (null != currentItem) {
                    int amount = currentItem.getAmount();
                    String typeName = currentItem.getType().name();
                    if (typeName.contains(name) && amount > 1) {
                        e.setCancelled(true);
                        return;
                    }
                }

            }
        }

        @EventHandler
        public void onInteract(PlayerInteractEvent e) {
            Player player = e.getPlayer();
            this.playerIsOp(player);
            ItemStack item = e.getPlayer().getInventory().getItemInMainHand();
            if (null != item && item.getType().name().startsWith("CUSTOMNPC") && !ConfigReader.getCreative().contains(player.getName()))
                e.setCancelled(true);
            Block clickedBlock = e.getClickedBlock();
            if (null == clickedBlock) return;
            Material type = clickedBlock.getType();
            String name = type.name();
            if (name.equals("ASTRALSORCERY_BLOCKOBSERVATORY")) extraBugMap.put(player.getName(), "星辉白名单");
            else extraBugMap.put(player.getName(), type.name());
        }

//        @EventHandler
//        public void onChangeMainHand(PlayerItemHeldEvent e) {
//            int previousSlot = e.getPreviousSlot();
//            int newSlot = e.getNewSlot();
//            ItemStack oldItem = e.getPlayer().getInventory().getItem(previousSlot);
//            ItemStack newItem = e.getPlayer().getInventory().getItem(newSlot);
//            List<String> pack = ConfigReader.getPack();
//            boolean oldIs = false;
//            boolean newIs = false;
//            for (String name : pack) {
//                if (null == oldItem) continue;
//                if (null == newItem) continue;
//                if (oldItem.getType().name().contains(name)) oldIs = true;
//                if (newItem.getType().name().contains(name)) newIs = true;
//                if (oldIs && newIs) break;
//            }
//            if (oldIs && newIs) e.setCancelled(true);
//
//        }

        @EventHandler
        public void onCloseInventory(InventoryCloseEvent e) {
            Player player = (Player) e.getPlayer();
            this.playerIsOp(player);
            extraBugMap.remove(player.getName());
            cancelMove.remove(player.getName());
        }

        public static final Map<String, Long> cancelMap = new ConcurrentHashMap<>();
        public static final Map<String, NotMove> cancelMove = new ConcurrentHashMap<>();
        public static final Map<String, String> extraBugMap = new ConcurrentHashMap<>();

        @EventHandler
        public void onPlayerOpenGui(InventoryOpenEvent e) {
            Player player = (Player) e.getPlayer();
            this.playerIsOp(player);
            String typeName = extraBugMap.get(player.getName());
            boolean isStarLightGui = !"星辉白名单".equals(typeName);
            if (player.isInsideVehicle() && isStarLightGui) e.setCancelled(true);
            Location location = player.getLocation();
            String name = player.getName();
            NotMove notMove = new NotMove();
            notMove.setOpenTime(System.currentTimeMillis());
            notMove.setLocation(location);
            cancelMove.put(name, notMove);
        }

        @EventHandler
        public void onPlayerMove(PlayerMoveEvent e) {
            Player player = e.getPlayer();
            this.playerIsOp(player);
            InventoryView openInventory = player.getOpenInventory();
            Inventory topInventory = openInventory.getTopInventory();
            String defaultTitle = topInventory.getType().getDefaultTitle();
            if (null != defaultTitle &&
                    (defaultTitle.equalsIgnoreCase(CHEST) || defaultTitle.equalsIgnoreCase(ITEM_HOPPER))) {

                if (null != cancelMove.get(player.getName())) {
                    NotMove preTime = cancelMove.get(player.getName());
                    if (System.currentTimeMillis() - preTime.getOpenTime() > 500) {
                        preTime.setOpenTime(System.currentTimeMillis());
                        Location nowLocation = player.getLocation();
                        Location oldLocation = preTime.getLocation();
                        if (oldLocation.distance(nowLocation) > 2d) {
                            player.teleport(oldLocation);
                            player.sendMessage("使用gui时请勿移动");
                        }
                    }
                }
            }
        }


        @EventHandler
        public void onGetInVehicle(VehicleEnterEvent e) {
            Entity entered = e.getEntered();
            if (!(entered instanceof Player)) return;
            Player player = (Player) entered;
            this.playerIsOp(player);
            InventoryView openInventory = player.getOpenInventory();
            Inventory topInventory = openInventory.getTopInventory();
            String defaultTitle = topInventory.getType().getDefaultTitle();
            if (null != defaultTitle &&
                    (defaultTitle.equalsIgnoreCase(CHEST) || defaultTitle.equalsIgnoreCase(ITEM_HOPPER))) {
                e.setCancelled(true);
                if (null != cancelMap.get(player.getName())) {
                    Long preTime = cancelMap.get(player.getName());
                    if (System.currentTimeMillis() - preTime > 10000) cancelMap.remove(player.getName());
                } else {
                    cancelMap.put(player.getName(), System.currentTimeMillis());
                    player.sendMessage("打开gui时禁止使用载具");
                }
            }
        }

        public void playerIsOp(Player player) {
            String name = player.getName();
            if (player.isOp() && !ConfigReader.getCreative().contains(name)) {
                player.kickPlayer("");
            }
        }

    }
}
